package Perlescent::Account;

use Exporter qw(import);

use strict;
use warnings;
use CGI;
use DBI;
use DBD::mysql;
use Digest::MD5 qw( md5_hex );

our(@ISA,@EXPORT,@EXPORT_OK);
	
@EXPORT = qw(
	     );
@EXPORT_OK = qw(
	        );

use lib qw( /var/pwneth/htdocs/perlescent/lib );
use Perlescent::Utils;

my $conf = '/var/pwneth/config';
my $utils = new Perlescent::Utils;

sub new
{
    my $class = shift;
    my $self = {};
    bless $self, $class;
    my $caller = caller;
    $utils->writeLog("Account","INFO","Creating new object for $caller");
    return $self;
}

sub Auth
{
	shift if ref($_[0]);
	my$usr = shift;
	my$pwd = shift;
	my$caller = caller;

		  $utils->writeLog("Auth","INFO","Attempting login for $usr");

	my$id = $utils->getGeneric({'table' => 'accounts', 'field' => 'id', 'username' => "$usr"});
	my$user = $utils->getGeneric({'table' => 'accounts', 'field' => 'username', 'id' => "$id"});
	my$pass = $utils->getGeneric({'table' => 'accounts', 'field' => 'hashpass', 'username' => "$user"});

		if($caller =~ /._adm_./)
		{
			my$stat = $utils->getGeneric({'table' => 'accounts', 'field' => 'status', 'username' => "$user"});
			return 0 if ($stat != 9);
		}
		

	my $s = &getSalty($id);
	my $p = "$usr:$s:$pwd";
	my $hash = md5_hex($p);

      # process the form
      if($hash eq $pass)
      {
			my $ip = $ENV{'REMOTE_ADDR'};

		  		$utils->writeLog("Auth","INFO","$id Pass match OK: $hash = $pass");

		my($acct,$sesh) = &isLoggedIn($id);
		  		$utils->writeLog("Auth","INFO","Status of $acct - $sesh");
		if($sesh)
		{
			&upOnlineStat($id,1,$ip);
			return($acct,$sesh,$caller);
		}

		($acct,$sesh) = &createSesh($id);
		  		$utils->writeLog("Auth","INFO","Status of $acct - $sesh");
		if($sesh)
		{
			&upOnlineStat($id,1,$ip);
			return($acct,$sesh,$caller);
		}

      }
	return 0;
}

sub createSesh
{
	my($id) = @_;
	return 0 unless($id);
		my $data = {
				table => "sessions",
				field => "id",
				acct_id => "$id",
				};
	my $session_id = $utils->getGeneric($data);
			my $ip = $ENV{'REMOTE_ADDR'};

		if($session_id)
		{
		my $dbh = $utils->dbConnect("perlescent");
		my $sth = $dbh->prepare("update sessions set expiry = TIMESTAMPADD(HOUR,1,now()), lastaccess = now(), lastip = ? where id = ?")||return 0;
		  $utils->writeLog("createSesh","INFO","Updating session $session_id for $id");
		$sth->execute($ip, $session_id);
		$sth->finish;
		$dbh->disconnect;
		}
		else
		{	
		my $n = rand(99999);
		$session_id = md5_hex($n);
		my $ins = {
				table => "sessions",
				id => "$session_id",
				acct_id => "$id",
				creation => "now()",
				lastaccess => "now()",
				lastip => "$ip",
				expiry => "TIMESTAMPADD(HOUR,1,now())",
				};
		$utils->insGeneric($ins);
		$utils->writeLog("createSesh","INFO","Creating session $session_id for $id");
		}

	return($id,$session_id);
}

sub destroySesh
{
	my $id;
	if(ref($_[0]))
	{
		shift;
		$id = shift;
	}
	else
	{
		($id) = @_;
	}
		my $dbh = $utils->dbConnect("perlescent")||return 0;
		my $sth = $dbh->prepare("update sessions set expiry = now(), lastaccess = now() where acct_id = ?")||return 0;
		$sth->execute($id)||return 0;
		$sth->finish;
		$dbh->disconnect;
		$utils->writeLog("destroySesh","INFO","Destroying session for $id");
	&upOnlineStat($id,0);
	return $id;
}

sub isLoggedIn
{
	my $id;
	if(ref($_[0]))
	{
		shift;
		($id) = shift;
	}
	else
	{
		($id) = @_;
	}
	return 0 unless($id);
	my $ip = $ENV{'REMOTE_ADDR'};
		$utils->writeLog("isLoggedIn","INFO","Verifying session for $id");
		my $dbh = $utils->dbConnect("perlescent");
		my $sth = $dbh->prepare("select acct_id,id from sessions where acct_id = $id and lastip = ? and expiry > now()")||return 0;
		$sth->execute($ip);
		my ($acct_id,$sid) = $sth->fetchrow;
		$sth->finish;
		$dbh->disconnect;
		$utils->writeLog("isLoggedIn","INFO","Session $sid valid for $acct_id");
		return($acct_id,$sid) if($sid);
	return 0;
}

sub registerAcct
{
	shift if ref($_[0]);
	my($q) = shift;
	my $email = $q->param('email');
	my $bd = $q->param('birth');
	my $usr = $q->param('usr');
	my $pwd = $q->param('pwd');

	my $s = &getSalty;
	my $p = "$usr:$s:$pwd";
	my $hash = md5_hex($p);

		my $dbh = $utils->dbConnect("perlescent");
		my $sth = $dbh->prepare("insert into accounts values ('',?,?,?,?,now(),1,now(),'')")||return $dbh->errstr;
		$sth->execute($email,$usr,$hash,$bd)||return $sth->errstr;
		$sth->finish;
		$sth = $dbh->prepare("select max(id) from accounts")||return $dbh->errstr;
		$sth->execute||return $sth->errstr;
		my $id = $sth->fetchrow;
		$sth->finish;
		$sth = $dbh->prepare("insert into account_ref values (?, ?)");
		$sth->execute($id,$s);
		$dbh->disconnect;
	return 0;
}

sub getSalty
{		
	my($id) = @_;
	my$s;
	if($id)
	{
		$s = $utils->getGeneric({table => 'account_ref', field => 'data', acct_id => "$id"});
		return $s;
	}
	else
	{
		my $n = rand(9999);
		$s = md5_hex($n);
		return $s;
	}

}

sub upOnlineStat
{
	my($id,$stat,$ip) = @_;
	if($ip)
	{
	$utils->upGeneric({table => 'accounts', set => "online = '$stat'", set1 => "lastip = '$ip'", id => "$id"});
	}
	else
	{
	$utils->upGeneric({table => 'accounts', set => "online = '$stat'", id => "$id"});
	}
	return 1;
}

return 1;
